using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Dungeon_Dive
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;        
        ContentManager contentManager;

        Console console;
        XMLEngine xmlEngine;
        PythonEngine pyEngine;
        Log log;
        public FPSCounter FPSCounter { get; set; }
        Random rng;

        MainMenuScreen menuScreen;
        MainScreen mainScreen;
        PauseMenuScreen pauseScreen;
        HelpScreen helpScreen;
        CreditScreen creditScreen;
        GameScreen activeScreen;
        GameScreen previousScreen;
        public GameOverScreen GameOverScreen { get; set; }

        KeyboardState oldstate;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {            
            Services.AddService(typeof(GraphicsDeviceManager), graphics);

            log = new Log("log.txt");
            Services.AddService(typeof(Log), log);

            contentManager = new ContentManager(this);
            Components.Add(contentManager);
            Services.AddService(typeof(ContentManager), contentManager);

            pyEngine = new PythonEngine();
            Services.AddService(typeof(PythonEngine), pyEngine);
            pyEngine.RunScriptFromString("clr.AddReference(\"Dungeon Dive\")");
            pyEngine.RunScriptFromString("from Dungeon_Dive import *");
            pyEngine.SetVariable("parentGame", this);
            pyEngine.SetVariable("log", log);

            xmlEngine = new XMLEngine();
            Services.AddService(typeof(XMLEngine), xmlEngine);

            console = new Console(this);
            //Components.Add(console);
            Services.AddService(typeof(Console), console);

            rng = new Random();
            Services.AddService(typeof(Random), rng);

            mainScreen = new MainScreen(this);
            Components.Add(mainScreen);

            menuScreen = new MainMenuScreen(this);
            Components.Add(menuScreen);

            pauseScreen = new PauseMenuScreen(this);
            Components.Add(pauseScreen);

            helpScreen = new HelpScreen(this);
            Components.Add(helpScreen);

            GameOverScreen = new GameOverScreen(this);
            Components.Add(GameOverScreen);

            creditScreen = new CreditScreen(this);
            Components.Add(creditScreen);

            activeScreen = menuScreen;
            activeScreen.Show();

            Components.Add(console); // Added to Components here so it gets drawn on top of level

            FPSCounter = new FPSCounter(this);
            FPSCounter.Visible = false;
            Components.Add(FPSCounter);

            oldstate = Keyboard.GetState();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            log.Write("Game1.LoadContent()");
            
            console.Font = Content.Load<SpriteFont>("Fonts\\Debugfont");
            FPSCounter.Font = Content.Load<SpriteFont>("Fonts\\Debugfont");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
        }

        /// <summary>
        /// Game1's Update manages screen transitions and menu input.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (activeScreen == menuScreen)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Enter) && oldstate.IsKeyDown(Keys.Enter))
                {
                    if (menuScreen.MainMenu.GetSelected() == 0)
                    {                        
                        if (File.Exists(mainScreen.SAVEFILENAME))
                        {
                            mainScreen.LoadProgress();
                        }
                        ActivateScreen(mainScreen);
                    }
                    if (menuScreen.MainMenu.GetSelected() == 1)
                    {
                        mainScreen.ResetLevel();
                        ActivateScreen(mainScreen);
                    }
                    if (menuScreen.MainMenu.GetSelected() == 2)
                    {
                        ActivateScreen(helpScreen);
                    }
                    if (menuScreen.MainMenu.GetSelected() == 3)
                    {
                        ActivateScreen(creditScreen);
                    }
                    if (menuScreen.MainMenu.GetSelected() == 4)
                    {
                        this.Exit();
                    }
                }
                if (Keyboard.GetState().IsKeyUp(Keys.Up) && oldstate.IsKeyDown(Keys.Up))
                    menuScreen.MainMenu.Up();
                if (Keyboard.GetState().IsKeyUp(Keys.Down) && oldstate.IsKeyDown(Keys.Down))
                    menuScreen.MainMenu.Down();               
            }

            if (activeScreen == mainScreen)
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Escape) && oldstate.IsKeyDown(Keys.Escape))
                {
                    ActivateScreen(pauseScreen);
                }
                if (Keyboard.GetState().IsKeyUp(Keys.P) && oldstate.IsKeyDown(Keys.P))
                {
                    ActivateScreen(pauseScreen);
                }
            }

            if (activeScreen == pauseScreen)
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Enter) && oldstate.IsKeyDown(Keys.Enter))
                {
                    if (pauseScreen.PauseMenu.GetSelected() == 0)
                    {
                        ActivateScreen(mainScreen);
                    }
                    if (pauseScreen.PauseMenu.GetSelected() == 1)
                    {                        
                        ActivateScreen(helpScreen);
                    }
                    if (pauseScreen.PauseMenu.GetSelected() == 2)
                    {
                        mainScreen.SaveProgress();
                        ActivateScreen(menuScreen);
                    }
                }
                if (Keyboard.GetState().IsKeyUp(Keys.Up) && oldstate.IsKeyDown(Keys.Up))
                    pauseScreen.PauseMenu.Up();
                if (Keyboard.GetState().IsKeyUp(Keys.Down) && oldstate.IsKeyDown(Keys.Down))
                    pauseScreen.PauseMenu.Down();
            }
            if (activeScreen == helpScreen)
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Space) && oldstate.IsKeyDown(Keys.Space))
                {
                    ActivateScreen(previousScreen);
                }
            }
            if (activeScreen == creditScreen)
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Space) && oldstate.IsKeyDown(Keys.Space))
                {
                    ActivateScreen(menuScreen);
                }
            }
            if (activeScreen == GameOverScreen)
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Enter) && oldstate.IsKeyDown(Keys.Enter))
                {
                    if (GameOverScreen.GameOverMenu.GetSelected() == 0)
                    {
                        mainScreen.ResetLevel();
                        mainScreen.SaveProgress();
                        ActivateScreen(mainScreen);
                    }
                    if (GameOverScreen.GameOverMenu.GetSelected() == 1)
                    {
                        mainScreen.ResetLevel();
                        mainScreen.SaveProgress();
                        ActivateScreen(menuScreen);
                    }
                }
                if (Keyboard.GetState().IsKeyUp(Keys.Up) && oldstate.IsKeyDown(Keys.Up))
                    GameOverScreen.GameOverMenu.Up();
                if (Keyboard.GetState().IsKeyUp(Keys.Down) && oldstate.IsKeyDown(Keys.Down))
                    GameOverScreen.GameOverMenu.Down();
            }

            oldstate = Keyboard.GetState();

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            //Cornflowerblue is no more
            GraphicsDevice.Clear(Color.Black);
            base.Draw(gameTime);
        }

        public void ActivateScreen(GameScreen active)
        {
            activeScreen.Hide();
            previousScreen = activeScreen;
            activeScreen = active;
            activeScreen.Show();
        }
    }
}
